Loading the required libraries


library(tidyverse)      # for data manipulation
library(DESeq2)         # for Differential gene expression analysis
library(ggplot2)        # for plotting
library(plotly)         # for interactive plots
library(GenomicRanges)  # for creating and manipulating genomic ranges
library(mixOmics)       # for PCA

Importing data


assay<- read.csv("assay.csv", row.names = 1)  # Importing gene expression assay data
Warning in file(file, "rt") :
  cannot open file 'assay.csv': No such file or directory
Error in file(file, "rt") : cannot open the connection

Printing all data

Visualizing variability in library size

ggplotly(lsize)
Warning: The following aesthetics were dropped during statistical transformation: label.
ℹ This can happen when ggplot fails to infer the correct grouping structure in the data.
ℹ Did you forget to specify a `group` aesthetic or to convert a numerical variable into a factor?

Filtering out low count genes

Filtering low-count genes is a common preprocessing step in RNA-Seq data analysis, especially when using tools like DESeq2 for differential expression analysis. Here’s why it’s important:

Low-Count Genes Provide Little Statistical Power

Genes with low counts typically have high variability due to the limited sampling of sequencing reads. This variability makes it difficult to reliably detect significant differences in expression levels between conditions.

Reduction of Multiple Testing Burden

Differential expression analysis involves statistical tests for thousands of genes. Each test adds to the multiple-testing burden, requiring more stringent p-value adjustments.

Minimizing Noise

Low-count genes are often affected by: Sequencing noise: Random fluctuations during library preparation or sequencing. Mapping artifacts: Reads mapped spuriously to regions with minimal biological relevance.

We are usnig the following filters

rowSums(Exp.data > 0) >= 2: At least 2 samples with non-zero expression.
rowSums(Exp.data) >= 20: Total expression across samples is at least 20
paste0("Number of genes after filtering: ", nrow(assay.filtered))
[1] "Number of genes after filtering: 201"

Visualizing RLE

A Relative Log Expression (RLE) plot is a diagnostic tool commonly used in RNA-Seq data analysis to assess the normalization of a count matrix. It shows the log ratios of gene expression counts relative to their median across samples.

Creating DEseq2 object with filtered counts

In DESeq2, the primary data structure for storing RNA-Seq data and performing analyses is the DESeqDataSet (DDS) object. It is specifically designed to handle the raw counts and associated metadata for differential expression analysis.

What is a DESeqDataSet?

A DESeqDataSet is an object from the S4 class system in R that holds:

Count Data: The raw, unnormalized read counts for genes across samples.

Column Metadata: Information about the experimental design (e.g., condition, batch).

Row Metadata: Gene annotations or other feature-level metadata.

Design Formula: Specifies the experimental design to model differential expression (e.g., ~ condition or ~ condition + batch).

Note: DESeq2 take raw counts as input

DE.obj <- DESeqDataSetFromMatrix(countData = assay.filtered,
                                 colData   = colData,
                                 metadata  = rowRanges,
                                 design    = ~ Sample_Group)
Error in getListElement(x, i, ...) : 
  GRanges objects don't support [[, as.list(), lapply(), or unlist() at the moment

Estimating size factor and normalizing counts

DESeq2 performs normalization using ‘size factor’ to account for differences in sequencing depth and other systematic biases across samples in RNA-Seq datasets.

The size factor is a scaling factor used in RNA-Seq analysis to normalize read counts across samples, accounting for differences in sequencing depth or library size. This ensures that comparisons of gene expression levels are not biased by variations in the total number of reads per sample.

Visualizing data

Principal Component Analysis (PCA) is a dimensionality reduction technique widely used in data analysis, including RNA-Seq or other high-dimensional datasets. It transforms the data into a new coordinate system such that the greatest variance lies along the first principal component (PC1), the second greatest variance along the second component (PC2), and so on.

Performing Differential expression analysis

DESeq2 performs differential expression gene (DEG) analysis using a model-based approach designed specifically for count data from RNA-Seq experiments. It employs generalized linear models (GLMs) and statistical techniques to identify genes with significant differences in expression across conditions.

Normalization

Dispersion Estimation

Model fitting

Hypothesis Testing

Multiple Testing Correction


DE.obj$Sample_Group <- relevel(DE.obj$Sample_Group, ref = "HK")  # Setting reference group

DE.obj <- DESeq(DE.obj)                                          #Fitting the model
using pre-existing size factors
estimating dispersions
found already estimated dispersions, replacing these
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
res.con <- results(DE.obj,                                       # Extracting result table
                   contrast=c("Sample_Group", "WT", "HK"),       # Setting Contrast 
                   pAdjustMethod = "BH",                         # Using 'BH' for p-value adjustment
                   alpha = 0.1)                                  # Adjusted p-value threshold
                   
res.con <- res.con[!is.na(res.con$padj),]                        # Removing genes with NA adj p-values                  

Visualizing results

LS0tCnRpdGxlOiAiUk5BX1NlcXVlbmNpbmciCmF1dGhvcjogIkFidSBTYWFkYXQiCmRhdGU6ICIyMDI0LTEyLTA0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyBMb2FkaW5nIHRoZSByZXF1aXJlZCBsaWJyYXJpZXMKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICAjIGZvciBkYXRhIG1hbmlwdWxhdGlvbgpsaWJyYXJ5KERFU2VxMikgICAgICAgICAjIGZvciBEaWZmZXJlbnRpYWwgZ2VuZSBleHByZXNzaW9uIGFuYWx5c2lzCmxpYnJhcnkoZ2dwbG90MikgICAgICAgICMgZm9yIHBsb3R0aW5nCmxpYnJhcnkocGxvdGx5KSAgICAgICAgICMgZm9yIGludGVyYWN0aXZlIHBsb3RzCmxpYnJhcnkoR2Vub21pY1JhbmdlcykgICMgZm9yIGNyZWF0aW5nIGFuZCBtYW5pcHVsYXRpbmcgZ2Vub21pYyByYW5nZXMKbGlicmFyeShtaXhPbWljcykgICAgICAgIyBmb3IgUENBCmBgYAoKIyMgSW1wb3J0aW5nIGRhdGEKCmBgYHtyfQoKYXNzYXk8LSByZWFkLmNzdigiYXNzYXkuY3N2Iiwgcm93Lm5hbWVzID0gMSkgICMgSW1wb3J0aW5nIGdlbmUgZXhwcmVzc2lvbiBhc3NheSBkYXRhCmNvbERhdGEgPC0gcmVhZC5jc3YoImNvbERhdGEuY3N2IikgICAgICAgICAgICAjIEltcG9ydGluZyBjbGluaWNhbCBpbmZvcm1hdGlvbgp0ZW1wPC0gcmVhZC5jc3YoInJhd1JhbmdlLmNzdiIpICAgICAgICAgICAgICAgIyBJbXBvcnRpbmcgcmF3UmFuZ2VzIGFzIGRhdGFmcmFtZQoKcm93UmFuZ2VzIDwtIEdSYW5nZXMoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjcmVhdGluZyByYXdSYW5nZXMgZnJvbSBkYXRhZnJhbWdlCiAgICAgICAgICAgICBzZXFuYW1lcyA9IFJsZSh0ZW1wJGNociksICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ2hyb21vc29tZSBuYW1lcwogICAgICAgICAgICAgcmFuZ2VzID0gSVJhbmdlcyhzdGFydCA9IHRlbXAkc3RhcnQsIGVuZCA9dGVtcCRlbmQpLCAjIFN0YXJ0IGFuZCBFbmQgcG9zaXRpb25zCiAgICAgICAgICAgICBzdHJhbmQgPSBSbGUodGVtcCRzdHJhbmQpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICMgU3RyYW5kIGluZm9ybWF0aW9uIChpZiBhdmFpbGFibGUpCiAgICAgICAgICAgICBkYXRhLmZyYW1lKEdlbmUgPSB0ZW1wJEdlbmUsIExlbmd0aCA9IHRlbXAkbGVuZ3RoKSkgICMgQWRkaXRpb25hbCBjb2x1bW5zCgpgYGAKCiMjIFByaW50aW5nIGFsbCBkYXRhCgpgYGB7cn0KCnByaW50KCJUaGUgY291bnQgZGF0YSBhcyBBc3NheTogIikKaGVhZChhc3NheSkKCnByaW50KCJUaGUgY2xpbmljYWwgZGF0YSBkYXRhIGFzIGNvbERhdGE6ICIpCmhlYWQoY29sRGF0YSkKCnByaW50KCJUaGUgZ2VuZSBjb29yZGluYXRlcyBhcyByYXdSYW5nZXMgIikKaGVhZChyb3dSYW5nZXMpCgpgYGAKCiMjIFZpc3VhbGl6aW5nIHZhcmlhYmlsaXR5IGluIGxpYnJhcnkgc2l6ZQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCm5yZWFkcyA8LSBkYXRhLmZyYW1lKHJlYWRzID0gY29sU3Vtcyhhc3NheSkpICU+JSAgICAgICAgICAgICAgICAgICAjIENhbGN1bGF0aW5nIGxpYnJhcnkgc2l6ZSBieSBzdW1taW5nIHJlYWQgY291bnRzIGZvciBlYWNoIHNhbXBsZQogIHJvd25hbWVzX3RvX2NvbHVtbigic2FtcGxlIikgJT4lCiAgbXV0YXRlKFNhbXBsZV9Hcm91cCA9IGNhc2Vfd2hlbihncmVwbCgiSEsiLCBzYW1wbGUpIH4gIkhLIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJXVCIsIHNhbXBsZSkgfiAiV1QiKSkgCgpsc2l6ZSA8LSBnZ3Bsb3QobnJlYWRzLCBhZXMoeD1TYW1wbGVfR3JvdXAsIHk9cmVhZHMsIGZpbGw9U2FtcGxlX0dyb3VwLGxhYmVsPXNhbXBsZSkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjI1KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZm9yZXN0IGdyZWVuIiwgInN0ZWVsIGJsdWUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArIAogIGdndGl0bGUoIkxpYnJhcnkgc2l6ZSIpCgoKZ2dwbG90bHkobHNpemUpCgoKYGBgCgoKIyMgRmlsdGVyaW5nIG91dCBsb3cgY291bnQgZ2VuZXMKCkZpbHRlcmluZyBsb3ctY291bnQgZ2VuZXMgaXMgYSBjb21tb24gcHJlcHJvY2Vzc2luZyBzdGVwIGluIFJOQS1TZXEgZGF0YSBhbmFseXNpcywgZXNwZWNpYWxseSB3aGVuIHVzaW5nIHRvb2xzIGxpa2UgREVTZXEyIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4gCkhlcmUncyB3aHkgaXQncyBpbXBvcnRhbnQ6CgojIyMgTG93LUNvdW50IEdlbmVzIFByb3ZpZGUgTGl0dGxlIFN0YXRpc3RpY2FsIFBvd2VyCgpHZW5lcyB3aXRoIGxvdyBjb3VudHMgdHlwaWNhbGx5IGhhdmUgaGlnaCB2YXJpYWJpbGl0eSBkdWUgdG8gdGhlIGxpbWl0ZWQgc2FtcGxpbmcgb2Ygc2VxdWVuY2luZyByZWFkcy4gVGhpcyB2YXJpYWJpbGl0eSBtYWtlcyBpdCBkaWZmaWN1bHQgdG8gcmVsaWFibHkgZGV0ZWN0IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIGV4cHJlc3Npb24gbGV2ZWxzIGJldHdlZW4gY29uZGl0aW9ucy4KCiMjIyBSZWR1Y3Rpb24gb2YgTXVsdGlwbGUgVGVzdGluZyBCdXJkZW4KCkRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIGludm9sdmVzIHN0YXRpc3RpY2FsIHRlc3RzIGZvciB0aG91c2FuZHMgb2YgZ2VuZXMuIEVhY2ggdGVzdCBhZGRzIHRvIHRoZSBtdWx0aXBsZS10ZXN0aW5nIGJ1cmRlbiwgcmVxdWlyaW5nIG1vcmUgc3RyaW5nZW50IHAtdmFsdWUgYWRqdXN0bWVudHMuCgojIyMgTWluaW1pemluZyBOb2lzZQoKTG93LWNvdW50IGdlbmVzIGFyZSBvZnRlbiBhZmZlY3RlZCBieToKU2VxdWVuY2luZyBub2lzZTogUmFuZG9tIGZsdWN0dWF0aW9ucyBkdXJpbmcgbGlicmFyeSBwcmVwYXJhdGlvbiBvciBzZXF1ZW5jaW5nLgpNYXBwaW5nIGFydGlmYWN0czogUmVhZHMgbWFwcGVkIHNwdXJpb3VzbHkgdG8gcmVnaW9ucyB3aXRoIG1pbmltYWwgYmlvbG9naWNhbCByZWxldmFuY2UuCgojIyMjIFdlIGFyZSB1c25pZyB0aGUgZm9sbG93aW5nIGZpbHRlcnMKCiMjIyMjIHJvd1N1bXMoRXhwLmRhdGEgPiAwKSA+PSAyOiBBdCBsZWFzdCAyIHNhbXBsZXMgd2l0aCBub24temVybyBleHByZXNzaW9uLgojIyMjIyByb3dTdW1zKEV4cC5kYXRhKSA+PSAyMDogVG90YWwgZXhwcmVzc2lvbiBhY3Jvc3Mgc2FtcGxlcyBpcyBhdCBsZWFzdCAyMAoKYGBge3J9Cgphc3NheS5maWx0ZXJlZCA8LSBhc3NheVtyb3dTdW1zKGFzc2F5ID4gMCkgPj0gMiAmIHJvd1N1bXMoYXNzYXkpID49IDIwLF0KCnBhc3RlMCgiTnVtYmVyIG9mIGdlbmVzIGJlZm9yZSBmaWx0ZXJpbmc6ICIsIG5yb3coYXNzYXkpKQpwYXN0ZTAoIk51bWJlciBvZiBnZW5lcyBhZnRlciBmaWx0ZXJpbmc6ICIsIG5yb3coYXNzYXkuZmlsdGVyZWQpKQoKYGBgCgojIyBWaXN1YWxpemluZyBSTEUKCkEgUmVsYXRpdmUgTG9nIEV4cHJlc3Npb24gKFJMRSkgcGxvdCBpcyBhIGRpYWdub3N0aWMgdG9vbCBjb21tb25seSB1c2VkIGluIFJOQS1TZXEgZGF0YSBhbmFseXNpcyB0byBhc3Nlc3MgdGhlIG5vcm1hbGl6YXRpb24gb2YgYSBjb3VudCBtYXRyaXguIEl0IHNob3dzIHRoZSBsb2cgcmF0aW9zIG9mIGdlbmUgZXhwcmVzc2lvbiBjb3VudHMgcmVsYXRpdmUgdG8gdGhlaXIgbWVkaWFuIGFjcm9zcyBzYW1wbGVzLiAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UgLCB3YXJuaW5nPUZBTFNFfQoKIyBBZGQgcHNldWRvY291bnQgYW5kIGNhbGN1bGF0ZSBsb2cyLXRyYW5zZm9ybWVkIGNvdW50cwpsb2dfY291bnRzIDwtIGxvZzIoYXNzYXkuZmlsdGVyZWQgKyAxKQoKIyBDYWxjdWxhdGUgcmVsYXRpdmUgbG9nIGV4cHJlc3Npb24KbWVkaWFucyA8LSBhcHBseShsb2dfY291bnRzLCAxLCBtZWRpYW4pICAgICAgICAgIyBNZWRpYW4gZm9yIGVhY2ggZ2VuZSBhY3Jvc3Mgc2FtcGxlcwpybGUgPC0gc3dlZXAobG9nX2NvdW50cywgMSwgbWVkaWFucywgRlVOID0gIi0iKSAjIFN1YnRyYWN0IG1lZGlhbnMgKGxvZyBzY2FsZSkKCiMgUmVzaGFwZSBkYXRhIGZvciBnZ3Bsb3QKcmxlX2xvbmcgPC0gcmVzaGFwZTI6Om1lbHQocmxlKQpjb2xuYW1lcyhybGVfbG9uZykgPC0gYygiU2FtcGxlIiwgIkRldmlhdGlvbiIpCnJsZV9sb25nJFNhbXBsZV9ncm91cCA8LSAgcmVwKGMoIkhLIiwgIldUIiksIGMoMTAwNSwxMDA1KSkKCiMgUGxvdCBSTEUgYXMgYSBib3hwbG90IGNvbG9yZWQgYnkgU2FtcGxlX0dyb3VwCmdncGxvdChybGVfbG9uZywgYWVzKHggPSBTYW1wbGUsIHkgPSBEZXZpYXRpb24sIGZpbGwgPSBTYW1wbGVfZ3JvdXApKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDAuNSwgb3V0bGllci5jb2xvdXIgPSAicmVkIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImZvcmVzdCBncmVlbiIsICJzdGVlbCBibHVlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSTEUgUGxvdCBiZWZvcmUgTm9ybWFsaXphdGlvbiIsCiAgICB4ID0gIlNhbXBsZSIsCiAgICB5ID0gIlJlbGF0aXZlIExvZyBFeHByZXNzaW9uIChEZXZpYXRpb24pIiwKICAgIGZpbGwgPSAiU2FtcGxlX2dyb3VwIgogICkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIGNsYXJpdHkKCmBgYAoKIyMgQ3JlYXRpbmcgREVzZXEyIG9iamVjdCB3aXRoIGZpbHRlcmVkIGNvdW50cwoKSW4gREVTZXEyLCB0aGUgcHJpbWFyeSBkYXRhIHN0cnVjdHVyZSBmb3Igc3RvcmluZyBSTkEtU2VxIGRhdGEgYW5kIHBlcmZvcm1pbmcgYW5hbHlzZXMgaXMgdGhlIERFU2VxRGF0YVNldCAoRERTKSBvYmplY3QuIEl0IGlzIHNwZWNpZmljYWxseSBkZXNpZ25lZCB0byBoYW5kbGUgdGhlIHJhdyBjb3VudHMgYW5kIGFzc29jaWF0ZWQgbWV0YWRhdGEgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKIyMjIFdoYXQgaXMgYSBERVNlcURhdGFTZXQ/CgpBIERFU2VxRGF0YVNldCBpcyBhbiBvYmplY3QgZnJvbSB0aGUgUzQgY2xhc3Mgc3lzdGVtIGluIFIgdGhhdCBob2xkczoKCiMjIyMgQ291bnQgRGF0YTogVGhlIHJhdywgdW5ub3JtYWxpemVkIHJlYWQgY291bnRzIGZvciBnZW5lcyBhY3Jvc3Mgc2FtcGxlcy4KIyMjIyBDb2x1bW4gTWV0YWRhdGE6IEluZm9ybWF0aW9uIGFib3V0IHRoZSBleHBlcmltZW50YWwgZGVzaWduIChlLmcuLCBjb25kaXRpb24sIGJhdGNoKS4KIyMjIyBSb3cgTWV0YWRhdGE6IEdlbmUgYW5ub3RhdGlvbnMgb3Igb3RoZXIgZmVhdHVyZS1sZXZlbCBtZXRhZGF0YS4KIyMjIyBEZXNpZ24gRm9ybXVsYTogU3BlY2lmaWVzIHRoZSBleHBlcmltZW50YWwgZGVzaWduIHRvIG1vZGVsIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIChlLmcuLCB+IGNvbmRpdGlvbiBvciB+IGNvbmRpdGlvbiArIGJhdGNoKS4KCiMjIyMgTm90ZTogREVTZXEyIHRha2UgcmF3IGNvdW50cyBhcyBpbnB1dAoKYGBge3IgbWVzc2FnZT1GQUxTRSAsIHdhcm5pbmc9RkFMU0V9CgpERS5vYmogPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBhc3NheS5maWx0ZXJlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSAgID0gY29sRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduICAgID0gfiBTYW1wbGVfR3JvdXApCgpgYGAKCiMjIEVzdGltYXRpbmcgc2l6ZSBmYWN0b3IgYW5kIG5vcm1hbGl6aW5nIGNvdW50cwoKREVTZXEyIHBlcmZvcm1zIG5vcm1hbGl6YXRpb24gdXNpbmcgJ3NpemUgZmFjdG9yJyB0byBhY2NvdW50IGZvciBkaWZmZXJlbmNlcyBpbiBzZXF1ZW5jaW5nIGRlcHRoIGFuZCBvdGhlciBzeXN0ZW1hdGljIGJpYXNlcyBhY3Jvc3Mgc2FtcGxlcyBpbiBSTkEtU2VxIGRhdGFzZXRzLgoKVGhlIHNpemUgZmFjdG9yIGlzIGEgc2NhbGluZyBmYWN0b3IgdXNlZCBpbiBSTkEtU2VxIGFuYWx5c2lzIHRvIG5vcm1hbGl6ZSByZWFkIGNvdW50cyBhY3Jvc3Mgc2FtcGxlcywgYWNjb3VudGluZyBmb3IgZGlmZmVyZW5jZXMgaW4gc2VxdWVuY2luZyBkZXB0aCBvciBsaWJyYXJ5IHNpemUuIFRoaXMgZW5zdXJlcyB0aGF0IGNvbXBhcmlzb25zIG9mIGdlbmUgZXhwcmVzc2lvbiBsZXZlbHMgYXJlIG5vdCBiaWFzZWQgYnkgdmFyaWF0aW9ucyBpbiB0aGUgdG90YWwgbnVtYmVyIG9mIHJlYWRzIHBlciBzYW1wbGUuCgpgYGB7ciBtZXNzYWdlPUZBTFNFICwgd2FybmluZz1GQUxTRX0KCkRFLm9iaiA8LSBlc3RpbWF0ZVNpemVGYWN0b3JzKERFLm9iaikgICAgICAgICAgICAjIEVzdGltYXRpbmcgc2l6ZSBmYWN0b3IKIApERS5ub3JtYWxpemVkIDwtIGNvdW50cyhERS5vYmosIG5vcm1hbGl6ZWQgPSBUKSAgIyBOb3JtYWxpemluZyBjb3VudHMKCiMgQWRkIHBzZXVkb2NvdW50IGFuZCBjYWxjdWxhdGUgbG9nMi10cmFuc2Zvcm1lZCBjb3VudHMKbG9nX2NvdW50cyA8LSBsb2cyKERFLm5vcm1hbGl6ZWQgKyAxKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgojIENhbGN1bGF0ZSByZWxhdGl2ZSBsb2cgZXhwcmVzc2lvbgptZWRpYW5zIDwtIGFwcGx5KGxvZ19jb3VudHMsIDEsIG1lZGlhbikgICAgICAgICAjIE1lZGlhbiBmb3IgZWFjaCBnZW5lIGFjcm9zcyBzYW1wbGVzCnJsZSA8LSBzd2VlcChsb2dfY291bnRzLCAxLCBtZWRpYW5zLCBGVU4gPSAiLSIpICMgU3VidHJhY3QgbWVkaWFucyAobG9nIHNjYWxlKQoKIyBSZXNoYXBlIGRhdGEgZm9yIGdncGxvdApybGVfbG9uZyA8LSByZXNoYXBlMjo6bWVsdChybGUpCmNvbG5hbWVzKHJsZV9sb25nKSA8LSBjKCJTYW1wbGUiLCAiRGV2aWF0aW9uIikKcmxlX2xvbmckU2FtcGxlX2dyb3VwIDwtICByZXAoYygiSEsiLCAiV1QiKSwgYygxMDA1LDEwMDUpKQoKIyBQbG90IFJMRSBhcyBhIGJveHBsb3QgY29sb3JlZCBieSBTYW1wbGVfR3JvdXAKZ2dwbG90KHJsZV9sb25nLCBhZXMoeCA9IFNhbXBsZSwgeSA9IERldmlhdGlvbiwgZmlsbCA9IFNhbXBsZV9ncm91cCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMC41LCBvdXRsaWVyLmNvbG91ciA9ICJyZWQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZm9yZXN0IGdyZWVuIiwgInN0ZWVsIGJsdWUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlJMRSBQbG90IGFmdGVyIE5vcm1hbGl6YXRpb24iLAogICAgeCA9ICJTYW1wbGUiLAogICAgeSA9ICJSZWxhdGl2ZSBMb2cgRXhwcmVzc2lvbiAoRGV2aWF0aW9uKSIsCiAgICBmaWxsID0gIlNhbXBsZV9ncm91cCIKICApICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBjbGFyaXR5CgpgYGAKCiMjIFZpc3VhbGl6aW5nIGRhdGEKClByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgKFBDQSkgaXMgYSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdGVjaG5pcXVlIHdpZGVseSB1c2VkIGluIGRhdGEgYW5hbHlzaXMsIGluY2x1ZGluZyBSTkEtU2VxIG9yIG90aGVyIGhpZ2gtZGltZW5zaW9uYWwgZGF0YXNldHMuIEl0IHRyYW5zZm9ybXMgdGhlIGRhdGEgaW50byBhIG5ldyBjb29yZGluYXRlIHN5c3RlbSBzdWNoIHRoYXQgdGhlIGdyZWF0ZXN0IHZhcmlhbmNlIGxpZXMgYWxvbmcgdGhlIGZpcnN0IHByaW5jaXBhbCBjb21wb25lbnQgKFBDMSksIHRoZSBzZWNvbmQgZ3JlYXRlc3QgdmFyaWFuY2UgYWxvbmcgdGhlIHNlY29uZCBjb21wb25lbnQgKFBDMiksIGFuZCBzbyBvbi4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpwY2ExPC0gcGNhKHQoREUubm9ybWFsaXplZCksIGNlbnRlciA9IFQsIHNjYWxlID0gVCkgICAgICAgIyBQZXJmb3JtaW5nIFBDQQoKcGxvdEluZGl2KHBjYTEsIGdyb3VwID0gY29sRGF0YSRTYW1wbGVfR3JvdXAsIGluZC5uYW1lcyA9IEYsIAogICAgICAgICAgdGl0bGUgPSAiVG90YWwgZXhwcmVzc2lvbiBwcm9maWxlIiwKICAgICAgICAgIGxlZ2VuZCA9IFQsIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBjb2wucGVyLmdyb3VwID0gYygiZm9yZXN0IGdyZWVuIiwgInN0ZWVsIGJsdWUiKSkKCmBgYAoKIyMgUGVyZm9ybWluZyBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcwoKREVTZXEyIHBlcmZvcm1zIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGdlbmUgKERFRykgYW5hbHlzaXMgdXNpbmcgYSBtb2RlbC1iYXNlZCBhcHByb2FjaCBkZXNpZ25lZCBzcGVjaWZpY2FsbHkgZm9yIGNvdW50IGRhdGEgZnJvbSBSTkEtU2VxIGV4cGVyaW1lbnRzLiBJdCBlbXBsb3lzIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbHMgKEdMTXMpIGFuZCBzdGF0aXN0aWNhbCB0ZWNobmlxdWVzIHRvIGlkZW50aWZ5IGdlbmVzIHdpdGggc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gZXhwcmVzc2lvbiBhY3Jvc3MgY29uZGl0aW9ucy4KCiMjIyMgTm9ybWFsaXphdGlvbgojIyMjIERpc3BlcnNpb24gRXN0aW1hdGlvbgojIyMjIE1vZGVsIGZpdHRpbmcKIyMjIyBIeXBvdGhlc2lzIFRlc3RpbmcKIyMjIyBNdWx0aXBsZSBUZXN0aW5nIENvcnJlY3Rpb24KCmBgYHtyICBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKREUub2JqJFNhbXBsZV9Hcm91cCA8LSByZWxldmVsKERFLm9iaiRTYW1wbGVfR3JvdXAsIHJlZiA9ICJISyIpICAjIFNldHRpbmcgcmVmZXJlbmNlIGdyb3VwCgpERS5vYmogPC0gREVTZXEoREUub2JqKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNGaXR0aW5nIHRoZSBtb2RlbAoKcmVzLmNvbiA8LSByZXN1bHRzKERFLm9iaiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEV4dHJhY3RpbmcgcmVzdWx0IHRhYmxlCiAgICAgICAgICAgICAgICAgICBjb250cmFzdD1jKCJTYW1wbGVfR3JvdXAiLCAiV1QiLCAiSEsiKSwgICAgICAgIyBTZXR0aW5nIENvbnRyYXN0IAogICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsICAgICAgICAgICAgICAgICAgICAgICAgICMgVXNpbmcgJ0JIJyBmb3IgcC12YWx1ZSBhZGp1c3RtZW50CiAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGp1c3RlZCBwLXZhbHVlIHRocmVzaG9sZAogICAgICAgICAgICAgICAgICAgCnJlcy5jb24gPC0gcmVzLmNvblshaXMubmEocmVzLmNvbiRwYWRqKSxdICAgICAgICAgICAgICAgICAgICAgICAgIyBSZW1vdmluZyBnZW5lcyB3aXRoIE5BIGFkaiBwLXZhbHVlcyAgICAgICAgICAgICAgICAgIAoKCmBgYAoKIyMgVmlzdWFsaXppbmcgcmVzdWx0cwoKYGBge3IgIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cgp2b2xjYW5vIDwtIGFzLmRhdGEuZnJhbWUocmVzLmNvbikgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJnZW5lIikgJT4lCiAgbXV0YXRlKExvZ3BhZGo9LWxvZzEwKHBhZGopKSAlPiUKICBtdXRhdGUoc2lnPWNhc2Vfd2hlbihsb2cyRm9sZENoYW5nZSA+PSAxICYgcGFkaiA8IDAuMDUgfiAiVXAiLAogICAgICAgICAgICAgICAgICAgICAgIGxvZzJGb2xkQ2hhbmdlIDw9IC0xICYgcGFkaiA8IDAuMDUgfiAiRG93biIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIHk9TG9ncGFkaiwgY29sb3I9c2lnLCBsYWJlbD1nZW5lKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MSkgKwogIHRoZW1lX2J3KCkgKyAKICB5bGFiKCItTG9nMTAoRkRSKSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImZpcmVicmljayIsICJzdGVlbGJsdWUiKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoLTEsIDEpLCBjb2wgPSAiZ3JheSIsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBjb2wgPSAiZ3JheSIsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpICsKICBnZ3RpdGxlKCJWb2xjYW5vIERFR3MiKQogIAoKZ2dwbG90bHkodm9sY2FubykKCgpgYGAKCg==